home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 March / PCWorld_2008-03_cd.bin / v cisle / mobiDVD / MobiDVD-1.0.0.6.exe / xulrunner / modules / XPCOMUtils.jsm
Text File  |  2007-07-18  |  8KB  |  228 lines

  1. /*
  2.  * ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is Mozilla code.
  16.  *
  17.  * The Initial Developer of the Original Code is
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 2004
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *    Alex Fritze <alex@croczilla.com> (original author)
  24.  *    Nickolay Ponomarev <asqueella@gmail.com>
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  28.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the MPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the MPL, the GPL or the LGPL.
  37.  *
  38.  * ***** END LICENSE BLOCK ***** */
  39.  
  40. /**
  41.  * Utilities for JavaScript components loaded by the JS component
  42.  * loader.
  43.  *
  44.  * Import into a JS component using
  45.  * 'Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");'
  46.  *
  47.  * Exposing a JS 'class' as a component using these utility methods consists
  48.  * of several steps:
  49.  * 0. Import XPCOMUtils, as described above.
  50.  * 1. Declare the 'class' (or multiple classes) implementing the component(s):
  51.  *  function MyComponent() {
  52.  *    // constructor
  53.  *  }
  54.  *  MyComponent.prototype = {
  55.  *    // properties required for XPCOM registration:
  56.  *    classDescription: "unique text description",
  57.  *    classID:          Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
  58.  *    contractID:       "@example.com/xxx;1",
  59.  *
  60.  *    // [optional] custom factory (an object implementing nsIFactory). If not
  61.  *    // provided, the default factory is used, which returns
  62.  *    // |(new MyComponent()).QueryInterface(iid)| in its createInstance().
  63.  *    _xpcom_factory: { ... }
  64.  *
  65.  *    // QueryInterface implementation, e.g. using the generateQI helper
  66.  *    QueryInterface: XPCOMUtils.generateQI(
  67.  *      [Components.interfaces.nsIObserver,
  68.  *       Components.interfaces.nsIMyInterface]),
  69.  *
  70.  *    // ...component implementation...
  71.  *  };
  72.  *
  73.  * 2. Create an array of component constructors (like the one
  74.  * created in step 1):
  75.  *  var components = [MyComponent];
  76.  *
  77.  * 3. Define the NSGetModule entry point:
  78.  *  function NSGetModule(compMgr, fileSpec) {
  79.  *    // components is the array created in step 2.
  80.  *    return XPCOMUtils.generateModule(components);
  81.  *  }
  82.  */
  83.  
  84.  
  85. EXPORTED_SYMBOLS = [ "XPCOMUtils" ];
  86.  
  87. const Ci = Components.interfaces;
  88.  
  89. var XPCOMUtils = {
  90.   /**
  91.    * Generate a QueryInterface implementation. The returned function must be
  92.    * assigned to the 'QueryInterface' property of a JS object. When invoked on
  93.    * that object, it checks if the given iid is listed in the |interfaces|
  94.    * param, and if it is, returns |this| (the object it was called on).
  95.    */
  96.   generateQI: function(interfaces) {
  97.     return makeQI([i.name for each(i in interfaces)]);
  98.   },
  99.  
  100.   /**
  101.    * Generate the NSGetModule function (along with the module definition).
  102.    * See the parameters to generateModule.
  103.    */
  104.   generateNSGetModule: function(componentsArray, postRegister, preUnregister) {
  105.     return function NSGetModule(compMgr, fileSpec) {
  106.       return XPCOMUtils.generateModule(componentsArray,
  107.                                        postRegister,
  108.                                        preUnregister);
  109.     }
  110.   },
  111.  
  112.   /**
  113.    * Generate a module implementation.
  114.    *
  115.    * @param componentsArray  Array of component constructors. See the comment
  116.    *                         at the top of this file for details.
  117.    * @param postRegister  optional post-registration function with
  118.    *                      signature 'postRegister(nsIComponentManager,
  119.    *                                              nsIFile, componentsArray)'
  120.    * @param preUnregister optional pre-unregistration function with
  121.    *                      signature 'preUnregister(nsIComponentManager,
  122.    *                                               nsIFile, componentsArray)'
  123.    */
  124.   generateModule: function(componentsArray, postRegister, preUnregister) {
  125.     let classes = [];
  126.     for each (let component in componentsArray) {
  127.       classes.push({
  128.         cid:          component.prototype.classID,
  129.         className:    component.prototype.classDescription,
  130.         contractID:   component.prototype.contractID,
  131.         factory:      this._getFactory(component),
  132.       });
  133.     }
  134.  
  135.     return { // nsIModule impl.
  136.       getClassObject: function(compMgr, cid, iid) {
  137.         if (!iid.equals(Ci.nsIFactory))
  138.           throw Components.results.NS_ERROR_NO_INTERFACE;
  139.  
  140.         for each (let classDesc in classes) {
  141.           if (classDesc.cid.equals(cid))
  142.             return classDesc.factory;
  143.         }
  144.  
  145.         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  146.       },
  147.  
  148.       registerSelf: function(compMgr, fileSpec, location, type) {
  149.         var componentCount = 0;
  150.         debug("*** registering " + fileSpec.leafName + ": [ ");
  151.         compMgr.QueryInterface(Ci.nsIComponentRegistrar);
  152.         for each (let classDesc in classes) {
  153.           debug((componentCount++ ? ", " : "") + classDesc.className);
  154.           compMgr.registerFactoryLocation(classDesc.cid,
  155.                                           classDesc.className,
  156.                                           classDesc.contractID,
  157.                                           fileSpec,
  158.                                           location,
  159.                                           type);
  160.         }
  161.  
  162.         if (postRegister)
  163.           postRegister(compMgr, fileSpec, componentsArray);
  164.         debug(" ]\n");
  165.       },
  166.  
  167.       unregisterSelf: function(compMgr, fileSpec, location) {
  168.         var componentCount = 0;
  169.         debug("*** unregistering " + fileSpec.leafName + ": [ ");
  170.         compMgr.QueryInterface(Ci.nsIComponentRegistrar);
  171.         if (preUnregister)
  172.           preUnregister(compMgr, fileSpec, componentsArray);
  173.  
  174.         for each (let classDesc in classes) {
  175.           debug((componentCount++ ? ", " : "") + classDesc.className);
  176.           compMgr.unregisterFactoryLocation(classDesc.cid, fileSpec);
  177.         }
  178.         debug(" ]\n");
  179.       },
  180.  
  181.       canUnload: function(compMgr) {
  182.         return true;
  183.       }
  184.     };
  185.   },
  186.  
  187.   /**
  188.    * Convenience access to category manager
  189.    */
  190.   get categoryManager() {
  191.     return Components.classes["@mozilla.org/categorymanager;1"]
  192.            .getService(Ci.nsICategoryManager);
  193.   },
  194.  
  195.   /**
  196.    * Returns an nsIFactory for |component|.
  197.    */
  198.   _getFactory: function(component) {
  199.     var factory = component.prototype._xpcom_factory;
  200.     if (!factory) {
  201.       factory = {
  202.         createInstance: function(outer, iid) {
  203.           if(outer)
  204.             throw CR.NS_ERROR_NO_AGGREGATION;
  205.           return (new component()).QueryInterface(iid);
  206.         }
  207.       }
  208.     }
  209.     return factory;
  210.   }
  211. };
  212.  
  213. /**
  214.  * Helper for XPCOMUtils.generateQI to avoid leaks - see bug 381651#c1
  215.  */
  216. function makeQI(interfaceNames) {
  217.   return function XPCOMUtils_QueryInterface(iid) {
  218.     if (iid.equals(Ci.nsISupports))
  219.       return this;
  220.     for each(let interfaceName in interfaceNames) {
  221.       if (Ci[interfaceName].equals(iid))
  222.         return this;
  223.     }
  224.  
  225.     throw Components.results.NS_ERROR_NO_INTERFACE;
  226.   };
  227. }
  228.